package skiree.host.abetsy.service.core.mgtv;

import cn.hutool.core.util.CharsetUtil;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.vdurmont.emoji.EmojiParser;
import org.springframework.stereotype.Component;
import skiree.host.abetsy.dao.LocalCommentMapper;
import skiree.host.abetsy.dao.LocalEpisodeMapper;
import skiree.host.abetsy.model.LocalComment;
import skiree.host.abetsy.model.LocalEpisode;
import skiree.host.abetsy.service.core.Stratege;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

@Component
public class MgtvProcess implements Stratege {

    @Resource
    private LocalEpisodeMapper localEpisodeMapper;

    @Resource
    private LocalCommentMapper localCommentMapper;

    @Override
    public void loadDanMu(LocalEpisode localEpisodeOld) {
        // 先检查localEpisode状态
        LocalEpisode localEpisode = localEpisodeMapper.selectById(localEpisodeOld.getId());
        if (localEpisode.getStatus().equals("init")) {
            localEpisode.setStatus("loading");
            localEpisode.setTime(new Date());
            localEpisodeMapper.updateById(localEpisode);
            Matcher matcher = Pattern.compile("/(\\d+)/(\\d+)\\.html").matcher(localEpisode.getUrl());
            if (matcher.find()) {
                String cid = matcher.group(1);
                String vid = matcher.group(2);
                String mgUrl = "https://pcweb.api.mgtv.com/video/info?cid=" + cid + "&vid=" + vid;
                String result = HttpUtil.get(mgUrl, CharsetUtil.CHARSET_UTF_8);
                String timeStr = JSONUtil.parseObj(result).getByPath("$.data.info.time", String.class);
                int allTime = (Integer.parseInt(timeStr.split(":")[0]) * 60) + Integer.parseInt(timeStr.split(":")[1]);
                List<LocalComment> comments = new ArrayList<>();
                for (Integer i = 0; i < allTime; i += 60) {
                    String danMuUrl = "https://galaxy.bz.mgtv.com/rdbarrage?cid=" + cid + "&vid=" + vid + "&time=" + i * 1000;
                    getExtraDanMu(comments, danMuUrl, localEpisodeOld);
                }
                // 时间相同的弹幕只保留三条
                comments = comments.stream().collect(Collectors.groupingBy(LocalComment::getT)).values().stream().flatMap(list -> list.stream().limit(3)).collect(Collectors.toList());
                localCommentMapper.insert(comments);
            }
        }
    }

    public static void getExtraDanMu(List<LocalComment> comments, String url, LocalEpisode localEpisode) {
        String result = HttpUtil.get(url, CharsetUtil.CHARSET_UTF_8);
        if (JSONUtil.parse(result).getByPath("$.data.items") == null) return;
        JSONArray jsonArray = JSONUtil.parseArray(JSONUtil.parse(result).getByPath("$.data.items").toString());
        for (Object object : jsonArray) {
            JSONObject data = JSONUtil.parseObj(object.toString());
            String content = data.getStr("content");
            content = EmojiParser.removeAllEmojis(content);
            if (!content.isEmpty()) {
                Long offset = data.getLong("time");
                BigDecimal start = new BigDecimal("0.00");
                if (offset != 0) {
                    start = new BigDecimal(offset).divide(new BigDecimal(1000), 2, RoundingMode.HALF_UP);
                }
                String time = start.toString();
                String style = "16777215";
                String position = "1";
                String userId = "[mgtv]";
                LocalComment localComment = new LocalComment();
                localComment.setEpisodeId(localEpisode.getId());
                localComment.setP(String.join(",", Arrays.asList(time, position, style, userId)));
                localComment.setM(content);
                localComment.setT(start);
                comments.add(localComment);
            }
        }
    }

    @Override
    public boolean supports(LocalEpisode localEpisode) {
        return localEpisode.getUrl().contains("www.mgtv.com");
    }

}